home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / python2.4 / httplib.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2005-10-18  |  36KB  |  1,320 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. '''HTTP/1.1 client library
  5.  
  6. <intro stuff goes here>
  7. <other stuff, too>
  8.  
  9. HTTPConnection go through a number of "states", which defines when a client
  10. may legally make another request or fetch the response for a particular
  11. request. This diagram details these state transitions:
  12.  
  13.     (null)
  14.       |
  15.       | HTTPConnection()
  16.       v
  17.     Idle
  18.       |
  19.       | putrequest()
  20.       v
  21.     Request-started
  22.       |
  23.       | ( putheader() )*  endheaders()
  24.       v
  25.     Request-sent
  26.       |
  27.       | response = getresponse()
  28.       v
  29.     Unread-response   [Response-headers-read]
  30.       |\\____________________
  31.       |                     |
  32.       | response.read()     | putrequest()
  33.       v                     v
  34.     Idle                  Req-started-unread-response
  35.                      ______/|
  36.                    /        |
  37.    response.read() |        | ( putheader() )*  endheaders()
  38.                    v        v
  39.        Request-started    Req-sent-unread-response
  40.                             |
  41.                             | response.read()
  42.                             v
  43.                           Request-sent
  44.  
  45. This diagram presents the following rules:
  46.   -- a second request may not be started until {response-headers-read}
  47.   -- a response [object] cannot be retrieved until {request-sent}
  48.   -- there is no differentiation between an unread response body and a
  49.      partially read response body
  50.  
  51. Note: this enforcement is applied by the HTTPConnection class. The
  52.       HTTPResponse class does not enforce this state machine, which
  53.       implies sophisticated clients may accelerate the request/response
  54.       pipeline. Caution should be taken, though: accelerating the states
  55.       beyond the above pattern may imply knowledge of the server\'s
  56.       connection-close behavior for certain requests. For example, it
  57.       is impossible to tell whether the server will close the connection
  58.       UNTIL the response headers have been read; this means that further
  59.       requests cannot be placed into the pipeline until it is known that
  60.       the server will NOT be closing the connection.
  61.  
  62. Logical State                  __state            __response
  63. -------------                  -------            ----------
  64. Idle                           _CS_IDLE           None
  65. Request-started                _CS_REQ_STARTED    None
  66. Request-sent                   _CS_REQ_SENT       None
  67. Unread-response                _CS_IDLE           <response_class>
  68. Req-started-unread-response    _CS_REQ_STARTED    <response_class>
  69. Req-sent-unread-response       _CS_REQ_SENT       <response_class>
  70. '''
  71. import errno
  72. import mimetools
  73. import socket
  74. from urlparse import urlsplit
  75.  
  76. try:
  77.     from cStringIO import StringIO
  78. except ImportError:
  79.     from StringIO import StringIO
  80.  
  81. __all__ = [
  82.     'HTTP',
  83.     'HTTPResponse',
  84.     'HTTPConnection',
  85.     'HTTPSConnection',
  86.     'HTTPException',
  87.     'NotConnected',
  88.     'UnknownProtocol',
  89.     'UnknownTransferEncoding',
  90.     'UnimplementedFileMode',
  91.     'IncompleteRead',
  92.     'InvalidURL',
  93.     'ImproperConnectionState',
  94.     'CannotSendRequest',
  95.     'CannotSendHeader',
  96.     'ResponseNotReady',
  97.     'BadStatusLine',
  98.     'error']
  99. HTTP_PORT = 80
  100. HTTPS_PORT = 443
  101. _UNKNOWN = 'UNKNOWN'
  102. _CS_IDLE = 'Idle'
  103. _CS_REQ_STARTED = 'Request-started'
  104. _CS_REQ_SENT = 'Request-sent'
  105. CONTINUE = 100
  106. SWITCHING_PROTOCOLS = 101
  107. PROCESSING = 102
  108. OK = 200
  109. CREATED = 201
  110. ACCEPTED = 202
  111. NON_AUTHORITATIVE_INFORMATION = 203
  112. NO_CONTENT = 204
  113. RESET_CONTENT = 205
  114. PARTIAL_CONTENT = 206
  115. MULTI_STATUS = 207
  116. IM_USED = 226
  117. MULTIPLE_CHOICES = 300
  118. MOVED_PERMANENTLY = 301
  119. FOUND = 302
  120. SEE_OTHER = 303
  121. NOT_MODIFIED = 304
  122. USE_PROXY = 305
  123. TEMPORARY_REDIRECT = 307
  124. BAD_REQUEST = 400
  125. UNAUTHORIZED = 401
  126. PAYMENT_REQUIRED = 402
  127. FORBIDDEN = 403
  128. NOT_FOUND = 404
  129. METHOD_NOT_ALLOWED = 405
  130. NOT_ACCEPTABLE = 406
  131. PROXY_AUTHENTICATION_REQUIRED = 407
  132. REQUEST_TIMEOUT = 408
  133. CONFLICT = 409
  134. GONE = 410
  135. LENGTH_REQUIRED = 411
  136. PRECONDITION_FAILED = 412
  137. REQUEST_ENTITY_TOO_LARGE = 413
  138. REQUEST_URI_TOO_LONG = 414
  139. UNSUPPORTED_MEDIA_TYPE = 415
  140. REQUESTED_RANGE_NOT_SATISFIABLE = 416
  141. EXPECTATION_FAILED = 417
  142. UNPROCESSABLE_ENTITY = 422
  143. LOCKED = 423
  144. FAILED_DEPENDENCY = 424
  145. UPGRADE_REQUIRED = 426
  146. INTERNAL_SERVER_ERROR = 500
  147. NOT_IMPLEMENTED = 501
  148. BAD_GATEWAY = 502
  149. SERVICE_UNAVAILABLE = 503
  150. GATEWAY_TIMEOUT = 504
  151. HTTP_VERSION_NOT_SUPPORTED = 505
  152. INSUFFICIENT_STORAGE = 507
  153. NOT_EXTENDED = 510
  154.  
  155. class HTTPMessage(mimetools.Message):
  156.     
  157.     def addheader(self, key, value):
  158.         '''Add header for field key handling repeats.'''
  159.         prev = self.dict.get(key)
  160.         if prev is None:
  161.             self.dict[key] = value
  162.         else:
  163.             combined = ', '.join((prev, value))
  164.             self.dict[key] = combined
  165.  
  166.     
  167.     def addcontinue(self, key, more):
  168.         '''Add more field data from a continuation line.'''
  169.         prev = self.dict[key]
  170.         self.dict[key] = prev + '\n ' + more
  171.  
  172.     
  173.     def readheaders(self):
  174.         '''Read header lines.
  175.  
  176.         Read header lines up to the entirely blank line that terminates them.
  177.         The (normally blank) line that ends the headers is skipped, but not
  178.         included in the returned list.  If a non-header line ends the headers,
  179.         (which is an error), an attempt is made to backspace over it; it is
  180.         never included in the returned list.
  181.  
  182.         The variable self.status is set to the empty string if all went well,
  183.         otherwise it is an error message.  The variable self.headers is a
  184.         completely uninterpreted list of lines contained in the header (so
  185.         printing them will reproduce the header exactly as it appears in the
  186.         file).
  187.  
  188.         If multiple header fields with the same name occur, they are combined
  189.         according to the rules in RFC 2616 sec 4.2:
  190.  
  191.         Appending each subsequent field-value to the first, each separated
  192.         by a comma. The order in which header fields with the same field-name
  193.         are received is significant to the interpretation of the combined
  194.         field value.
  195.         '''
  196.         self.dict = { }
  197.         self.unixfrom = ''
  198.         self.headers = hlist = []
  199.         self.status = ''
  200.         headerseen = ''
  201.         firstline = 1
  202.         startofline = None
  203.         unread = None
  204.         tell = None
  205.         if hasattr(self.fp, 'unread'):
  206.             unread = self.fp.unread
  207.         elif self.seekable:
  208.             tell = self.fp.tell
  209.         
  210.         while True:
  211.             if tell:
  212.                 
  213.                 try:
  214.                     startofline = tell()
  215.                 except IOError:
  216.                     startofline = None
  217.                     tell = None
  218.                     self.seekable = 0
  219.                 except:
  220.                     None<EXCEPTION MATCH>IOError
  221.                 
  222.  
  223.             None<EXCEPTION MATCH>IOError
  224.             line = self.fp.readline()
  225.             if not line:
  226.                 self.status = 'EOF in headers'
  227.                 break
  228.             
  229.             if firstline and line.startswith('From '):
  230.                 self.unixfrom = self.unixfrom + line
  231.                 continue
  232.             
  233.             firstline = 0
  234.             if headerseen and line[0] in ' \t':
  235.                 hlist.append(line)
  236.                 self.addcontinue(headerseen, line.strip())
  237.                 continue
  238.             elif self.iscomment(line):
  239.                 continue
  240.             elif self.islast(line):
  241.                 break
  242.             
  243.             headerseen = self.isheader(line)
  244.             if headerseen:
  245.                 hlist.append(line)
  246.                 self.addheader(headerseen, line[len(headerseen) + 1:].strip())
  247.                 continue
  248.                 continue
  249.             if not self.dict:
  250.                 self.status = 'No headers'
  251.             else:
  252.                 self.status = 'Non-header line where header expected'
  253.             if unread:
  254.                 unread(line)
  255.             elif tell:
  256.                 self.fp.seek(startofline)
  257.             else:
  258.                 self.status = self.status + '; bad seek'
  259.             break
  260.  
  261.  
  262.  
  263. class HTTPResponse:
  264.     
  265.     def __init__(self, sock, debuglevel = 0, strict = 0, method = None):
  266.         self.fp = sock.makefile('rb', 0)
  267.         self.debuglevel = debuglevel
  268.         self.strict = strict
  269.         self._method = method
  270.         self.msg = None
  271.         self.version = _UNKNOWN
  272.         self.status = _UNKNOWN
  273.         self.reason = _UNKNOWN
  274.         self.chunked = _UNKNOWN
  275.         self.chunk_left = _UNKNOWN
  276.         self.length = _UNKNOWN
  277.         self.will_close = _UNKNOWN
  278.  
  279.     
  280.     def _read_status(self):
  281.         line = self.fp.readline()
  282.         if self.debuglevel > 0:
  283.             print 'reply:', repr(line)
  284.         
  285.         if not line:
  286.             raise BadStatusLine(line)
  287.         
  288.         
  289.         try:
  290.             (version, status, reason) = line.split(None, 2)
  291.         except ValueError:
  292.             
  293.             try:
  294.                 (version, status) = line.split(None, 1)
  295.                 reason = ''
  296.             except ValueError:
  297.                 version = ''
  298.             except:
  299.                 None<EXCEPTION MATCH>ValueError
  300.             
  301.  
  302.             None<EXCEPTION MATCH>ValueError
  303.  
  304.         if not version.startswith('HTTP/'):
  305.             if self.strict:
  306.                 self.close()
  307.                 raise BadStatusLine(line)
  308.             else:
  309.                 self.fp = LineAndFileWrapper(line, self.fp)
  310.                 return ('HTTP/0.9', 200, '')
  311.         
  312.         
  313.         try:
  314.             status = int(status)
  315.             if status < 100 or status > 999:
  316.                 raise BadStatusLine(line)
  317.         except ValueError:
  318.             raise BadStatusLine(line)
  319.  
  320.         return (version, status, reason)
  321.  
  322.     
  323.     def begin(self):
  324.         if self.msg is not None:
  325.             return None
  326.         
  327.         while True:
  328.             (version, status, reason) = self._read_status()
  329.             if status != CONTINUE:
  330.                 break
  331.             
  332.             while True:
  333.                 skip = self.fp.readline().strip()
  334.                 if not skip:
  335.                     break
  336.                 
  337.                 if self.debuglevel > 0:
  338.                     print 'header:', skip
  339.                     continue
  340.         self.status = status
  341.         self.reason = reason.strip()
  342.         if version == 'HTTP/1.0':
  343.             self.version = 10
  344.         elif version.startswith('HTTP/1.'):
  345.             self.version = 11
  346.         elif version == 'HTTP/0.9':
  347.             self.version = 9
  348.         else:
  349.             raise UnknownProtocol(version)
  350.         if self.version == 9:
  351.             self.length = None
  352.             self.chunked = 0
  353.             self.will_close = 1
  354.             self.msg = HTTPMessage(StringIO())
  355.             return None
  356.         
  357.         self.msg = HTTPMessage(self.fp, 0)
  358.         if self.debuglevel > 0:
  359.             for hdr in self.msg.headers:
  360.                 print 'header:', hdr,
  361.             
  362.         
  363.         self.msg.fp = None
  364.         tr_enc = self.msg.getheader('transfer-encoding')
  365.         if tr_enc and tr_enc.lower() == 'chunked':
  366.             self.chunked = 1
  367.             self.chunk_left = None
  368.         else:
  369.             self.chunked = 0
  370.         self.will_close = self._check_close()
  371.         length = self.msg.getheader('content-length')
  372.         if length and not (self.chunked):
  373.             
  374.             try:
  375.                 self.length = int(length)
  376.             except ValueError:
  377.                 self.length = None
  378.             except:
  379.                 None<EXCEPTION MATCH>ValueError
  380.             
  381.  
  382.         None<EXCEPTION MATCH>ValueError
  383.         self.length = None
  384.         if not status == NO_CONTENT and status == NOT_MODIFIED:
  385.             if status <= status:
  386.                 pass
  387.             elif status < 200 or self._method == 'HEAD':
  388.                 self.length = 0
  389.             
  390.         if not (self.will_close) and not (self.chunked) and self.length is None:
  391.             self.will_close = 1
  392.         
  393.  
  394.     
  395.     def _check_close(self):
  396.         conn = self.msg.getheader('connection')
  397.         if self.version == 11:
  398.             conn = self.msg.getheader('connection')
  399.             if conn and 'close' in conn.lower():
  400.                 return True
  401.             
  402.             return False
  403.         
  404.         if self.msg.getheader('keep-alive'):
  405.             return False
  406.         
  407.         if conn and 'keep-alive' in conn.lower():
  408.             return False
  409.         
  410.         pconn = self.msg.getheader('proxy-connection')
  411.         if pconn and 'keep-alive' in pconn.lower():
  412.             return False
  413.         
  414.         return True
  415.  
  416.     
  417.     def close(self):
  418.         if self.fp:
  419.             self.fp.close()
  420.             self.fp = None
  421.         
  422.  
  423.     
  424.     def isclosed(self):
  425.         return self.fp is None
  426.  
  427.     
  428.     def read(self, amt = None):
  429.         if self.fp is None:
  430.             return ''
  431.         
  432.         if self.chunked:
  433.             return self._read_chunked(amt)
  434.         
  435.         if amt is None:
  436.             if self.length is None:
  437.                 s = self.fp.read()
  438.             else:
  439.                 s = self._safe_read(self.length)
  440.                 self.length = 0
  441.             self.close()
  442.             return s
  443.         
  444.         if self.length is not None:
  445.             if amt > self.length:
  446.                 amt = self.length
  447.             
  448.         
  449.         s = self.fp.read(amt)
  450.         if self.length is not None:
  451.             self.length -= len(s)
  452.         
  453.         return s
  454.  
  455.     
  456.     def _read_chunked(self, amt):
  457.         if not self.chunked != _UNKNOWN:
  458.             raise AssertionError
  459.         chunk_left = self.chunk_left
  460.         value = ''
  461.         while True:
  462.             if chunk_left is None:
  463.                 line = self.fp.readline()
  464.                 i = line.find(';')
  465.                 if i >= 0:
  466.                     line = line[:i]
  467.                 
  468.                 chunk_left = int(line, 16)
  469.                 if chunk_left == 0:
  470.                     break
  471.                 
  472.             
  473.             if amt is None:
  474.                 value += self._safe_read(chunk_left)
  475.             elif amt < chunk_left:
  476.                 value += self._safe_read(amt)
  477.                 self.chunk_left = chunk_left - amt
  478.                 return value
  479.             elif amt == chunk_left:
  480.                 value += self._safe_read(amt)
  481.                 self._safe_read(2)
  482.                 self.chunk_left = None
  483.                 return value
  484.             else:
  485.                 value += self._safe_read(chunk_left)
  486.                 amt -= chunk_left
  487.             self._safe_read(2)
  488.             chunk_left = None
  489.         while True:
  490.             line = self.fp.readline()
  491.             if line == '\r\n':
  492.                 break
  493.                 continue
  494.         self.close()
  495.         return value
  496.  
  497.     
  498.     def _safe_read(self, amt):
  499.         '''Read the number of bytes requested, compensating for partial reads.
  500.  
  501.         Normally, we have a blocking socket, but a read() can be interrupted
  502.         by a signal (resulting in a partial read).
  503.  
  504.         Note that we cannot distinguish between EOF and an interrupt when zero
  505.         bytes have been read. IncompleteRead() will be raised in this
  506.         situation.
  507.  
  508.         This function should be used when <amt> bytes "should" be present for
  509.         reading. If the bytes are truly not available (due to EOF), then the
  510.         IncompleteRead exception can be used to detect the problem.
  511.         '''
  512.         s = ''
  513.         while amt > 0:
  514.             chunk = self.fp.read(amt)
  515.             if not chunk:
  516.                 raise IncompleteRead(s)
  517.             
  518.             s += chunk
  519.             amt -= len(chunk)
  520.         return s
  521.  
  522.     
  523.     def getheader(self, name, default = None):
  524.         if self.msg is None:
  525.             raise ResponseNotReady()
  526.         
  527.         return self.msg.getheader(name, default)
  528.  
  529.     
  530.     def getheaders(self):
  531.         '''Return list of (header, value) tuples.'''
  532.         if self.msg is None:
  533.             raise ResponseNotReady()
  534.         
  535.         return self.msg.items()
  536.  
  537.  
  538.  
  539. class HTTPConnection:
  540.     _http_vsn = 11
  541.     _http_vsn_str = 'HTTP/1.1'
  542.     response_class = HTTPResponse
  543.     default_port = HTTP_PORT
  544.     auto_open = 1
  545.     debuglevel = 0
  546.     strict = 0
  547.     
  548.     def __init__(self, host, port = None, strict = None):
  549.         self.sock = None
  550.         self._buffer = []
  551.         self._HTTPConnection__response = None
  552.         self._HTTPConnection__state = _CS_IDLE
  553.         self._method = None
  554.         self._set_hostport(host, port)
  555.         if strict is not None:
  556.             self.strict = strict
  557.         
  558.  
  559.     
  560.     def _set_hostport(self, host, port):
  561.         if port is None:
  562.             i = host.rfind(':')
  563.             j = host.rfind(']')
  564.             if i > j:
  565.                 
  566.                 try:
  567.                     port = int(host[i + 1:])
  568.                 except ValueError:
  569.                     raise InvalidURL("nonnumeric port: '%s'" % host[i + 1:])
  570.  
  571.                 host = host[:i]
  572.             else:
  573.                 port = self.default_port
  574.             if host and host[0] == '[' and host[-1] == ']':
  575.                 host = host[1:-1]
  576.             
  577.         
  578.         self.host = host
  579.         self.port = port
  580.  
  581.     
  582.     def set_debuglevel(self, level):
  583.         self.debuglevel = level
  584.  
  585.     
  586.     def connect(self):
  587.         '''Connect to the host and port specified in __init__.'''
  588.         msg = 'getaddrinfo returns an empty list'
  589.         for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM):
  590.             (af, socktype, proto, canonname, sa) = res
  591.             
  592.             try:
  593.                 self.sock = socket.socket(af, socktype, proto)
  594.                 if self.debuglevel > 0:
  595.                     print 'connect: (%s, %s)' % (self.host, self.port)
  596.                 
  597.                 self.sock.connect(sa)
  598.             except socket.error:
  599.                 msg = None
  600.                 if self.debuglevel > 0:
  601.                     print 'connect fail:', (self.host, self.port)
  602.                 
  603.                 if self.sock:
  604.                     self.sock.close()
  605.                 
  606.                 self.sock = None
  607.                 continue
  608.  
  609.             break
  610.         
  611.         if not self.sock:
  612.             raise socket.error, msg
  613.         
  614.  
  615.     
  616.     def close(self):
  617.         '''Close the connection to the HTTP server.'''
  618.         if self.sock:
  619.             self.sock.close()
  620.             self.sock = None
  621.         
  622.         if self._HTTPConnection__response:
  623.             self._HTTPConnection__response.close()
  624.             self._HTTPConnection__response = None
  625.         
  626.         self._HTTPConnection__state = _CS_IDLE
  627.  
  628.     
  629.     def send(self, str):
  630.         """Send `str' to the server."""
  631.         if self.sock is None:
  632.             if self.auto_open:
  633.                 self.connect()
  634.             else:
  635.                 raise NotConnected()
  636.         
  637.         if self.debuglevel > 0:
  638.             print 'send:', repr(str)
  639.         
  640.         
  641.         try:
  642.             self.sock.sendall(str)
  643.         except socket.error:
  644.             v = None
  645.             if v[0] == 32:
  646.                 self.close()
  647.             
  648.             raise 
  649.  
  650.  
  651.     
  652.     def _output(self, s):
  653.         '''Add a line of output to the current request buffer.
  654.  
  655.         Assumes that the line does *not* end with \\r\\n.
  656.         '''
  657.         self._buffer.append(s)
  658.  
  659.     
  660.     def _send_output(self):
  661.         '''Send the currently buffered request and clear the buffer.
  662.  
  663.         Appends an extra \\r\\n to the buffer.
  664.         '''
  665.         self._buffer.extend(('', ''))
  666.         msg = '\r\n'.join(self._buffer)
  667.         del self._buffer[:]
  668.         self.send(msg)
  669.  
  670.     
  671.     def putrequest(self, method, url, skip_host = 0, skip_accept_encoding = 0):
  672.         """Send a request to the server.
  673.  
  674.         `method' specifies an HTTP request method, e.g. 'GET'.
  675.         `url' specifies the object being requested, e.g. '/index.html'.
  676.         `skip_host' if True does not add automatically a 'Host:' header
  677.         `skip_accept_encoding' if True does not add automatically an
  678.            'Accept-Encoding:' header
  679.         """
  680.         if self._HTTPConnection__response and self._HTTPConnection__response.isclosed():
  681.             self._HTTPConnection__response = None
  682.         
  683.         if self._HTTPConnection__state == _CS_IDLE:
  684.             self._HTTPConnection__state = _CS_REQ_STARTED
  685.         else:
  686.             raise CannotSendRequest()
  687.         self._method = method
  688.         if not url:
  689.             url = '/'
  690.         
  691.         str = '%s %s %s' % (method, url, self._http_vsn_str)
  692.         self._output(str)
  693.         if self._http_vsn == 11:
  694.             if not skip_host:
  695.                 netloc = ''
  696.                 if url.startswith('http'):
  697.                     (nil, netloc, nil, nil, nil) = urlsplit(url)
  698.                 
  699.                 if netloc:
  700.                     self.putheader('Host', netloc.encode('idna'))
  701.                 elif self.port == HTTP_PORT:
  702.                     self.putheader('Host', self.host.encode('idna'))
  703.                 else:
  704.                     self.putheader('Host', '%s:%s' % (self.host.encode('idna'), self.port))
  705.             
  706.             if not skip_accept_encoding:
  707.                 self.putheader('Accept-Encoding', 'identity')
  708.             
  709.         
  710.  
  711.     
  712.     def putheader(self, header, value):
  713.         """Send a request header line to the server.
  714.  
  715.         For example: h.putheader('Accept', 'text/html')
  716.         """
  717.         if self._HTTPConnection__state != _CS_REQ_STARTED:
  718.             raise CannotSendHeader()
  719.         
  720.         str = '%s: %s' % (header, value)
  721.         self._output(str)
  722.  
  723.     
  724.     def endheaders(self):
  725.         '''Indicate that the last header line has been sent to the server.'''
  726.         if self._HTTPConnection__state == _CS_REQ_STARTED:
  727.             self._HTTPConnection__state = _CS_REQ_SENT
  728.         else:
  729.             raise CannotSendHeader()
  730.         self._send_output()
  731.  
  732.     
  733.     def request(self, method, url, body = None, headers = { }):
  734.         '''Send a complete request to the server.'''
  735.         
  736.         try:
  737.             self._send_request(method, url, body, headers)
  738.         except socket.error:
  739.             v = None
  740.             if v[0] != 32 or not (self.auto_open):
  741.                 raise 
  742.             
  743.             self._send_request(method, url, body, headers)
  744.  
  745.  
  746.     
  747.     def _send_request(self, method, url, body, headers):
  748.         header_names = []([ k.lower() for k in headers ])
  749.         skips = { }
  750.         if 'accept-encoding' in header_names:
  751.             skips['skip_accept_encoding'] = 1
  752.         
  753.         self.putrequest(method, url, **skips)
  754.         if body and 'content-length' not in header_names:
  755.             self.putheader('Content-Length', str(len(body)))
  756.         
  757.         for hdr, value in headers.iteritems():
  758.             self.putheader(hdr, value)
  759.         
  760.         self.endheaders()
  761.         if body:
  762.             self.send(body)
  763.         
  764.  
  765.     
  766.     def getresponse(self):
  767.         '''Get the response from the server.'''
  768.         if self._HTTPConnection__response and self._HTTPConnection__response.isclosed():
  769.             self._HTTPConnection__response = None
  770.         
  771.         if self._HTTPConnection__state != _CS_REQ_SENT or self._HTTPConnection__response:
  772.             raise ResponseNotReady()
  773.         
  774.         if self.debuglevel > 0:
  775.             response = self.response_class(self.sock, self.debuglevel, strict = self.strict, method = self._method)
  776.         else:
  777.             response = self.response_class(self.sock, strict = self.strict, method = self._method)
  778.         response.begin()
  779.         if not response.will_close != _UNKNOWN:
  780.             raise AssertionError
  781.         self._HTTPConnection__state = _CS_IDLE
  782.         if response.will_close:
  783.             self.close()
  784.         else:
  785.             self._HTTPConnection__response = response
  786.         return response
  787.  
  788.  
  789.  
  790. class SharedSocket:
  791.     
  792.     def __init__(self, sock):
  793.         self.sock = sock
  794.         self._refcnt = 0
  795.  
  796.     
  797.     def incref(self):
  798.         self._refcnt += 1
  799.  
  800.     
  801.     def decref(self):
  802.         self._refcnt -= 1
  803.         if not self._refcnt >= 0:
  804.             raise AssertionError
  805.         self
  806.         if self._refcnt == 0:
  807.             self.sock.close()
  808.         
  809.  
  810.     
  811.     def __del__(self):
  812.         self.sock.close()
  813.  
  814.  
  815.  
  816. class SharedSocketClient:
  817.     
  818.     def __init__(self, shared):
  819.         self._closed = 0
  820.         self._shared = shared
  821.         self._shared.incref()
  822.         self._sock = shared.sock
  823.  
  824.     
  825.     def close(self):
  826.         if not self._closed:
  827.             self._shared.decref()
  828.             self._closed = 1
  829.             self._shared = None
  830.         
  831.  
  832.  
  833.  
  834. class SSLFile(SharedSocketClient):
  835.     '''File-like object wrapping an SSL socket.'''
  836.     BUFSIZE = 8192
  837.     
  838.     def __init__(self, sock, ssl, bufsize = None):
  839.         SharedSocketClient.__init__(self, sock)
  840.         self._ssl = ssl
  841.         self._buf = ''
  842.         if not bufsize:
  843.             pass
  844.         self._bufsize = self.__class__.BUFSIZE
  845.  
  846.     
  847.     def _read(self):
  848.         buf = ''
  849.         while True:
  850.             
  851.             try:
  852.                 buf = self._ssl.read(self._bufsize)
  853.             except socket.sslerror:
  854.                 err = None
  855.                 if err[0] == socket.SSL_ERROR_WANT_READ or err[0] == socket.SSL_ERROR_WANT_WRITE:
  856.                     continue
  857.                 
  858.                 if err[0] == socket.SSL_ERROR_ZERO_RETURN or err[0] == socket.SSL_ERROR_EOF:
  859.                     break
  860.                 
  861.                 raise 
  862.                 continue
  863.                 except socket.error:
  864.                     err = None
  865.                     if err[0] == errno.EINTR:
  866.                         continue
  867.                     
  868.                     if err[0] == errno.EBADF:
  869.                         break
  870.                     
  871.                     raise 
  872.                     continue
  873.                 else:
  874.                     break
  875.                 None<EXCEPTION MATCH>socket.error
  876.             return buf
  877.  
  878.  
  879.     
  880.     def read(self, size = None):
  881.         L = [
  882.             self._buf]
  883.         avail = len(self._buf)
  884.         while size is None or avail < size:
  885.             s = self._read()
  886.             if s == '':
  887.                 break
  888.             
  889.             L.append(s)
  890.             avail += len(s)
  891.         all = ''.join(L)
  892.         if size is None:
  893.             self._buf = ''
  894.             return all
  895.         else:
  896.             self._buf = all[size:]
  897.             return all[:size]
  898.  
  899.     
  900.     def readline(self):
  901.         L = [
  902.             self._buf]
  903.         self._buf = ''
  904.         while None:
  905.             i = L[-1].find('\n')
  906.             if i >= 0:
  907.                 break
  908.             
  909.             s = self._read()
  910.             if s == '':
  911.                 break
  912.             
  913.         if i == -1:
  914.             return ''.join(L)
  915.         else:
  916.             all = ''.join(L)
  917.             i = all.find('\n') + 1
  918.             line = all[:i]
  919.             self._buf = all[i:]
  920.             return line
  921.  
  922.     
  923.     def readlines(self, sizehint = 0):
  924.         total = 0
  925.         list = []
  926.         while True:
  927.             line = self.readline()
  928.             if not line:
  929.                 break
  930.             
  931.             list.append(line)
  932.             total += len(line)
  933.             if sizehint and total >= sizehint:
  934.                 break
  935.                 continue
  936.         return list
  937.  
  938.     
  939.     def fileno(self):
  940.         return self._sock.fileno()
  941.  
  942.     
  943.     def __iter__(self):
  944.         return self
  945.  
  946.     
  947.     def next(self):
  948.         line = self.readline()
  949.         if not line:
  950.             raise StopIteration
  951.         
  952.         return line
  953.  
  954.  
  955.  
  956. class FakeSocket(SharedSocketClient):
  957.     
  958.     class _closedsocket:
  959.         
  960.         def __getattr__(self, name):
  961.             raise error(9, 'Bad file descriptor')
  962.  
  963.  
  964.     
  965.     def __init__(self, sock, ssl):
  966.         sock = SharedSocket(sock)
  967.         SharedSocketClient.__init__(self, sock)
  968.         self._ssl = ssl
  969.  
  970.     
  971.     def close(self):
  972.         SharedSocketClient.close(self)
  973.         self._sock = self.__class__._closedsocket()
  974.  
  975.     
  976.     def makefile(self, mode, bufsize = None):
  977.         if mode != 'r' and mode != 'rb':
  978.             raise UnimplementedFileMode()
  979.         
  980.         return SSLFile(self._shared, self._ssl, bufsize)
  981.  
  982.     
  983.     def send(self, stuff, flags = 0):
  984.         return self._ssl.write(stuff)
  985.  
  986.     sendall = send
  987.     
  988.     def recv(self, len = 1024, flags = 0):
  989.         return self._ssl.read(len)
  990.  
  991.     
  992.     def __getattr__(self, attr):
  993.         return getattr(self._sock, attr)
  994.  
  995.  
  996.  
  997. class HTTPSConnection(HTTPConnection):
  998.     '''This class allows communication via SSL.'''
  999.     default_port = HTTPS_PORT
  1000.     
  1001.     def __init__(self, host, port = None, key_file = None, cert_file = None, strict = None):
  1002.         HTTPConnection.__init__(self, host, port, strict)
  1003.         self.key_file = key_file
  1004.         self.cert_file = cert_file
  1005.  
  1006.     
  1007.     def connect(self):
  1008.         '''Connect to a host on a given (SSL) port.'''
  1009.         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  1010.         sock.connect((self.host, self.port))
  1011.         ssl = socket.ssl(sock, self.key_file, self.cert_file)
  1012.         self.sock = FakeSocket(sock, ssl)
  1013.  
  1014.  
  1015.  
  1016. class HTTP:
  1017.     '''Compatibility class with httplib.py from 1.5.'''
  1018.     _http_vsn = 10
  1019.     _http_vsn_str = 'HTTP/1.0'
  1020.     debuglevel = 0
  1021.     _connection_class = HTTPConnection
  1022.     
  1023.     def __init__(self, host = '', port = None, strict = None):
  1024.         '''Provide a default host, since the superclass requires one.'''
  1025.         if port == 0:
  1026.             port = None
  1027.         
  1028.         self._setup(self._connection_class(host, port, strict))
  1029.  
  1030.     
  1031.     def _setup(self, conn):
  1032.         self._conn = conn
  1033.         self.send = conn.send
  1034.         self.putrequest = conn.putrequest
  1035.         self.endheaders = conn.endheaders
  1036.         self.set_debuglevel = conn.set_debuglevel
  1037.         conn._http_vsn = self._http_vsn
  1038.         conn._http_vsn_str = self._http_vsn_str
  1039.         self.file = None
  1040.  
  1041.     
  1042.     def connect(self, host = None, port = None):
  1043.         """Accept arguments to set the host/port, since the superclass doesn't."""
  1044.         if host is not None:
  1045.             self._conn._set_hostport(host, port)
  1046.         
  1047.         self._conn.connect()
  1048.  
  1049.     
  1050.     def getfile(self):
  1051.         """Provide a getfile, since the superclass' does not use this concept."""
  1052.         return self.file
  1053.  
  1054.     
  1055.     def putheader(self, header, *values):
  1056.         '''The superclass allows only one value argument.'''
  1057.         self._conn.putheader(header, '\r\n\t'.join(values))
  1058.  
  1059.     
  1060.     def getreply(self):
  1061.         '''Compat definition since superclass does not define it.
  1062.  
  1063.         Returns a tuple consisting of:
  1064.         - server status code (e.g. \'200\' if all goes well)
  1065.         - server "reason" corresponding to status code
  1066.         - any RFC822 headers in the response from the server
  1067.         '''
  1068.         
  1069.         try:
  1070.             response = self._conn.getresponse()
  1071.         except BadStatusLine:
  1072.             e = None
  1073.             self.file = self._conn.sock.makefile('rb', 0)
  1074.             self.close()
  1075.             self.headers = None
  1076.             return (-1, e.line, None)
  1077.  
  1078.         self.headers = response.msg
  1079.         self.file = response.fp
  1080.         return (response.status, response.reason, response.msg)
  1081.  
  1082.     
  1083.     def close(self):
  1084.         self._conn.close()
  1085.         self.file = None
  1086.  
  1087.  
  1088. if hasattr(socket, 'ssl'):
  1089.     
  1090.     class HTTPS(HTTP):
  1091.         '''Compatibility with 1.5 httplib interface
  1092.  
  1093.         Python 1.5.2 did not have an HTTPS class, but it defined an
  1094.         interface for sending http requests that is also useful for
  1095.         https.
  1096.         '''
  1097.         _connection_class = HTTPSConnection
  1098.         
  1099.         def __init__(self, host = '', port = None, key_file = None, cert_file = None, strict = None):
  1100.             if port == 0:
  1101.                 port = None
  1102.             
  1103.             self._setup(self._connection_class(host, port, key_file, cert_file, strict))
  1104.             self.key_file = key_file
  1105.             self.cert_file = cert_file
  1106.  
  1107.  
  1108.  
  1109.  
  1110. class HTTPException(Exception):
  1111.     pass
  1112.  
  1113.  
  1114. class NotConnected(HTTPException):
  1115.     pass
  1116.  
  1117.  
  1118. class InvalidURL(HTTPException):
  1119.     pass
  1120.  
  1121.  
  1122. class UnknownProtocol(HTTPException):
  1123.     
  1124.     def __init__(self, version):
  1125.         self.args = (version,)
  1126.         self.version = version
  1127.  
  1128.  
  1129.  
  1130. class UnknownTransferEncoding(HTTPException):
  1131.     pass
  1132.  
  1133.  
  1134. class UnimplementedFileMode(HTTPException):
  1135.     pass
  1136.  
  1137.  
  1138. class IncompleteRead(HTTPException):
  1139.     
  1140.     def __init__(self, partial):
  1141.         self.args = (partial,)
  1142.         self.partial = partial
  1143.  
  1144.  
  1145.  
  1146. class ImproperConnectionState(HTTPException):
  1147.     pass
  1148.  
  1149.  
  1150. class CannotSendRequest(ImproperConnectionState):
  1151.     pass
  1152.  
  1153.  
  1154. class CannotSendHeader(ImproperConnectionState):
  1155.     pass
  1156.  
  1157.  
  1158. class ResponseNotReady(ImproperConnectionState):
  1159.     pass
  1160.  
  1161.  
  1162. class BadStatusLine(HTTPException):
  1163.     
  1164.     def __init__(self, line):
  1165.         self.args = (line,)
  1166.         self.line = line
  1167.  
  1168.  
  1169. error = HTTPException
  1170.  
  1171. class LineAndFileWrapper:
  1172.     '''A limited file-like object for HTTP/0.9 responses.'''
  1173.     
  1174.     def __init__(self, line, file):
  1175.         self._line = line
  1176.         self._file = file
  1177.         self._line_consumed = 0
  1178.         self._line_offset = 0
  1179.         self._line_left = len(line)
  1180.  
  1181.     
  1182.     def __getattr__(self, attr):
  1183.         return getattr(self._file, attr)
  1184.  
  1185.     
  1186.     def _done(self):
  1187.         self._line_consumed = 1
  1188.         self.read = self._file.read
  1189.         self.readline = self._file.readline
  1190.         self.readlines = self._file.readlines
  1191.  
  1192.     
  1193.     def read(self, amt = None):
  1194.         if self._line_consumed:
  1195.             return self._file.read(amt)
  1196.         
  1197.         if not self._line_left:
  1198.             raise AssertionError
  1199.         if amt is None or amt > self._line_left:
  1200.             s = self._line[self._line_offset:]
  1201.             self._done()
  1202.             if amt is None:
  1203.                 return s + self._file.read()
  1204.             else:
  1205.                 return s + self._file.read(amt - len(s))
  1206.         elif not amt <= self._line_left:
  1207.             raise AssertionError
  1208.         i = self._line_offset
  1209.         j = i + amt
  1210.         s = self._line[i:j]
  1211.         self._line_offset = j
  1212.         self._line_left -= amt
  1213.         if self._line_left == 0:
  1214.             self._done()
  1215.         
  1216.         return s
  1217.  
  1218.     
  1219.     def readline(self):
  1220.         if self._line_consumed:
  1221.             return self._file.readline()
  1222.         
  1223.         if not self._line_left:
  1224.             raise AssertionError
  1225.         s = self._line[self._line_offset:]
  1226.         self._done()
  1227.         return s
  1228.  
  1229.     
  1230.     def readlines(self, size = None):
  1231.         if self._line_consumed:
  1232.             return self._file.readlines(size)
  1233.         
  1234.         if not self._line_left:
  1235.             raise AssertionError
  1236.         L = [
  1237.             self._line[self._line_offset:]]
  1238.         self._done()
  1239.         if size is None:
  1240.             return L + self._file.readlines()
  1241.         else:
  1242.             return L + self._file.readlines(size)
  1243.  
  1244.  
  1245.  
  1246. def test():
  1247.     '''Test this module.
  1248.  
  1249.     A hodge podge of tests collected here, because they have too many
  1250.     external dependencies for the regular test suite.
  1251.     '''
  1252.     import sys as sys
  1253.     import getopt as getopt
  1254.     (opts, args) = getopt.getopt(sys.argv[1:], 'd')
  1255.     dl = 0
  1256.     for o, a in opts:
  1257.         if o == '-d':
  1258.             dl = dl + 1
  1259.             continue
  1260.     
  1261.     host = 'www.python.org'
  1262.     selector = '/'
  1263.     if args[0:]:
  1264.         host = args[0]
  1265.     
  1266.     if args[1:]:
  1267.         selector = args[1]
  1268.     
  1269.     h = HTTP()
  1270.     h.set_debuglevel(dl)
  1271.     h.connect(host)
  1272.     h.putrequest('GET', selector)
  1273.     h.endheaders()
  1274.     (status, reason, headers) = h.getreply()
  1275.     print 'status =', status
  1276.     print 'reason =', reason
  1277.     print 'read', len(h.getfile().read())
  1278.     print 
  1279.     if headers:
  1280.         for header in headers.headers:
  1281.             print header.strip()
  1282.         
  1283.     
  1284.     print 
  1285.     
  1286.     class HTTP11(HTTP):
  1287.         _http_vsn = 11
  1288.         _http_vsn_str = 'HTTP/1.1'
  1289.  
  1290.     h = HTTP11('www.python.org')
  1291.     h.putrequest('GET', 'http://www.python.org/~jeremy/')
  1292.     h.endheaders()
  1293.     h.getreply()
  1294.     h.close()
  1295.     if hasattr(socket, 'ssl'):
  1296.         for host, selector in (('sourceforge.net', '/projects/python'),):
  1297.             print 'https://%s%s' % (host, selector)
  1298.             hs = HTTPS()
  1299.             hs.set_debuglevel(dl)
  1300.             hs.connect(host)
  1301.             hs.putrequest('GET', selector)
  1302.             hs.endheaders()
  1303.             (status, reason, headers) = hs.getreply()
  1304.             print 'status =', status
  1305.             print 'reason =', reason
  1306.             print 'read', len(hs.getfile().read())
  1307.             print 
  1308.             if headers:
  1309.                 for header in headers.headers:
  1310.                     print header.strip()
  1311.                 
  1312.             
  1313.             print 
  1314.         
  1315.     
  1316.  
  1317. if __name__ == '__main__':
  1318.     test()
  1319.  
  1320.